home *** CD-ROM | disk | FTP | other *** search
/ Aminet 25 / Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso / Aminet / game / shoot / ADoom_src_1_2.lha / ADoom_src / p_sight.c < prev    next >
C/C++ Source or Header  |  1998-02-19  |  7KB  |  358 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    LineOfSight/Visibility checks, uses REJECT Lookup Table.
  21. //
  22. //-----------------------------------------------------------------------------
  23.  
  24. static const char
  25. rcsid[] = "$Id: p_sight.c,v 1.3 1997/01/28 22:08:28 b1 Exp $";
  26.  
  27.  
  28. #include "doomdef.h"
  29.  
  30. #include "i_system.h"
  31. #include "p_local.h"
  32.  
  33. // State.
  34. #include "r_state.h"
  35.  
  36. //
  37. // P_CheckSight
  38. //
  39. fixed_t        sightzstart;        // eye z of looker
  40. fixed_t        topslope;
  41. fixed_t        bottomslope;        // slopes to top and bottom of target
  42.  
  43. divline_t    strace;            // from t1 to t2
  44. fixed_t        t2x;
  45. fixed_t        t2y;
  46.  
  47. int        sightcounts[2];
  48.  
  49.  
  50. //
  51. // P_DivlineSide
  52. // Returns side 0 (front), 1 (back), or 2 (on).
  53. //
  54. #ifdef AMIGA
  55. int
  56. P_DivlineSide
  57. ( fixed_t    x,
  58.   fixed_t    y,
  59.   divline_t*    node );
  60. #else
  61. int
  62. P_DivlineSide
  63. ( fixed_t    x,
  64.   fixed_t    y,
  65.   divline_t*    node )
  66. {
  67.     fixed_t    dx;
  68.     fixed_t    dy;
  69.     fixed_t    left;
  70.     fixed_t    right;
  71.  
  72.     if (!node->dx)
  73.     {
  74.     if (x==node->x)
  75.         return 2;
  76.     
  77.     if (x <= node->x)
  78.         return node->dy > 0;
  79.  
  80.     return node->dy < 0;
  81.     }
  82.     
  83.     if (!node->dy)
  84.     {
  85.     if (x==node->y)
  86.         return 2;
  87.  
  88.     if (y <= node->y)
  89.         return node->dx < 0;
  90.  
  91.     return node->dx > 0;
  92.     }
  93.     
  94.     dx = (x - node->x);
  95.     dy = (y - node->y);
  96.  
  97.     left =  (node->dy>>FRACBITS) * (dx>>FRACBITS);
  98.     right = (dy>>FRACBITS) * (node->dx>>FRACBITS);
  99.     
  100.     if (right < left)
  101.     return 0;    // front side
  102.     
  103.     if (left == right)
  104.     return 2;
  105.     return 1;        // back side
  106. }
  107. #endif
  108.  
  109.  
  110. //
  111. // P_InterceptVector2
  112. // Returns the fractional intercept point
  113. // along the first divline.
  114. // This is only called by the addthings and addlines traversers.
  115. //
  116. fixed_t
  117. P_InterceptVector2
  118. ( divline_t*    v2,
  119.   divline_t*    v1 )
  120. {
  121.     fixed_t    frac;
  122.     fixed_t    num;
  123.     fixed_t    den;
  124.     
  125.     den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
  126.  
  127.     if (den == 0)
  128.     return 0;
  129.     //    I_Error ("P_InterceptVector: parallel");
  130.     
  131.     num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + 
  132.     FixedMul ( (v2->y - v1->y)>>8 , v1->dx);
  133.     frac = FixedDiv (num , den);
  134.  
  135.     return frac;
  136. }
  137.  
  138. //
  139. // P_CrossSubsector
  140. // Returns true
  141. //  if strace crosses the given subsector successfully.
  142. //
  143. boolean P_CrossSubsector (int num)
  144. {
  145.     seg_t*        seg;
  146.     line_t*        line;
  147.     int            s1;
  148.     int            s2;
  149.     int            count;
  150.     subsector_t*    sub;
  151.     sector_t*        front;
  152.     sector_t*        back;
  153.     fixed_t        opentop;
  154.     fixed_t        openbottom;
  155.     divline_t        divl;
  156.     vertex_t*        v1;
  157.     vertex_t*        v2;
  158.     fixed_t        frac;
  159.     fixed_t        slope;
  160.     
  161. #ifdef RANGECHECK
  162.     if (num>=numsubsectors)
  163.     I_Error ("P_CrossSubsector: ss %i with numss = %i",
  164.          num,
  165.          numsubsectors);
  166. #endif
  167.  
  168.     sub = &subsectors[num];
  169.     
  170.     // check lines
  171.     count = sub->numlines;
  172.     seg = &segs[sub->firstline];
  173.  
  174.     for ( ; count ; seg++, count--)
  175.     {
  176.     line = seg->linedef;
  177.  
  178.     // allready checked other side?
  179.     if (line->validcount == validcount)
  180.         continue;
  181.     
  182.     line->validcount = validcount;
  183.         
  184.     v1 = line->v1;
  185.     v2 = line->v2;
  186.     s1 = P_DivlineSide (v1->x,v1->y, &strace);
  187.     s2 = P_DivlineSide (v2->x, v2->y, &strace);
  188.  
  189.     // line isn't crossed?
  190.     if (s1 == s2)
  191.         continue;
  192.     
  193.     divl.x = v1->x;
  194.     divl.y = v1->y;
  195.     divl.dx = v2->x - v1->x;
  196.     divl.dy = v2->y - v1->y;
  197.     s1 = P_DivlineSide (strace.x, strace.y, &divl);
  198.     s2 = P_DivlineSide (t2x, t2y, &divl);
  199.  
  200.     // line isn't crossed?
  201.     if (s1 == s2)
  202.         continue;    
  203.  
  204.     // stop because it is not two sided anyway
  205.     // might do this after updating validcount?
  206.     if ( !(line->flags & ML_TWOSIDED) )
  207.         return false;
  208.     
  209.     // crosses a two sided line
  210.     front = seg->frontsector;
  211.     back = seg->backsector;
  212.  
  213.     // no wall to block sight with?
  214.     if (front->floorheight == back->floorheight
  215.         && front->ceilingheight == back->ceilingheight)
  216.         continue;    
  217.  
  218.     // possible occluder
  219.     // because of ceiling height differences
  220.     if (front->ceilingheight < back->ceilingheight)
  221.         opentop = front->ceilingheight;
  222.     else
  223.         opentop = back->ceilingheight;
  224.  
  225.     // because of ceiling height differences
  226.     if (front->floorheight > back->floorheight)
  227.         openbottom = front->floorheight;
  228.     else
  229.         openbottom = back->floorheight;
  230.         
  231.     // quick test for totally closed doors
  232.     if (openbottom >= opentop)    
  233.         return false;        // stop
  234.     
  235.     frac = P_InterceptVector2 (&strace, &divl);
  236.         
  237.     if (front->floorheight != back->floorheight)
  238.     {
  239.         slope = FixedDiv (openbottom - sightzstart , frac);
  240.         if (slope > bottomslope)
  241.         bottomslope = slope;
  242.     }
  243.         
  244.     if (front->ceilingheight != back->ceilingheight)
  245.     {
  246.         slope = FixedDiv (opentop - sightzstart , frac);
  247.         if (slope < topslope)
  248.         topslope = slope;
  249.     }
  250.         
  251.     if (topslope <= bottomslope)
  252.         return false;        // stop                
  253.     }
  254.     // passed the subsector ok
  255.     return true;        
  256. }
  257.  
  258.  
  259.  
  260. //
  261. // P_CrossBSPNode
  262. // Returns true
  263. //  if strace crosses the given node successfully.
  264. //
  265. boolean P_CrossBSPNode (int bspnum)
  266. {
  267.     node_t*    bsp;
  268.     int        side;
  269.  
  270.     if (bspnum & NF_SUBSECTOR)
  271.     {
  272.     if (bspnum == -1)
  273.         return P_CrossSubsector (0);
  274.     else
  275.         return P_CrossSubsector (bspnum&(~NF_SUBSECTOR));
  276.     }
  277.         
  278.     bsp = &nodes[bspnum];
  279.     
  280.     // decide which side the start point is on
  281.     side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp);
  282.     if (side == 2)
  283.     side = 0;    // an "on" should cross both sides
  284.  
  285.     // cross the starting side
  286.     if (!P_CrossBSPNode (bsp->children[side]) )
  287.     return false;
  288.     
  289.     // the partition plane is crossed here
  290.     if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp))
  291.     {
  292.     // the line doesn't touch the other side
  293.     return true;
  294.     }
  295.     
  296.     // cross the ending side        
  297.     return P_CrossBSPNode (bsp->children[side^1]);
  298. }
  299.  
  300.  
  301. //
  302. // P_CheckSight
  303. // Returns true
  304. //  if a straight line between t1 and t2 is unobstructed.
  305. // Uses REJECT.
  306. //
  307. boolean
  308. P_CheckSight
  309. ( mobj_t*    t1,
  310.   mobj_t*    t2 )
  311. {
  312.     int        s1;
  313.     int        s2;
  314.     int        pnum;
  315.     int        bytenum;
  316.     int        bitnum;
  317.     
  318.     // First check for trivial rejection.
  319.  
  320.     // Determine subsector entries in REJECT table.
  321.     s1 = (t1->subsector->sector - sectors);
  322.     s2 = (t2->subsector->sector - sectors);
  323.     pnum = s1*numsectors + s2;
  324.     bytenum = pnum>>3;
  325.     bitnum = 1 << (pnum&7);
  326.  
  327.     // Check in REJECT table.
  328.     if (rejectmatrix[bytenum]&bitnum)
  329.     {
  330.     sightcounts[0]++;
  331.  
  332.     // can't possibly be connected
  333.     return false;    
  334.     }
  335.  
  336.     // An unobstructed LOS is possible.
  337.     // Now look from eyes of t1 to any part of t2.
  338.     sightcounts[1]++;
  339.  
  340.     validcount++;
  341.     
  342.     sightzstart = t1->z + t1->height - (t1->height>>2);
  343.     topslope = (t2->z+t2->height) - sightzstart;
  344.     bottomslope = (t2->z) - sightzstart;
  345.     
  346.     strace.x = t1->x;
  347.     strace.y = t1->y;
  348.     t2x = t2->x;
  349.     t2y = t2->y;
  350.     strace.dx = t2->x - t1->x;
  351.     strace.dy = t2->y - t1->y;
  352.  
  353.     // the head node is the last node output
  354.     return P_CrossBSPNode (numnodes-1);    
  355. }
  356.  
  357.  
  358.